//------------------------------------------------------------------------------
// exa.c
//
// SVG
//
// Group: 6295, Study assistant: Manuel Weber
//
// Authors:
// Daniel Lobenwein #0513094
// Marina Piculjan  #0830702
//
// Latest Changes: 01.03.2011
//------------------------------------------------------------------------------
//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAGIC_NUMBER "YASVG"

#define HEADER "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n\
  <!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics\
/SVG/1.1/DTD/svg11.dtd\">\n\
  <svg width=\"%d\" height=\"%d\" xmlns=\"http://www.w3.org/2000/svg\" \
xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n"

#define FOOTER "</svg>\n"
#define PARAMETER "-c="

#define SVG_TAG_CIRCLE "<circle cx=\"%d\" cy=\"%d\" r=\"%d\" fill=\"%s\" \
  stroke=\"%s\" stroke-width=\"%d\"  />\n"

#define SVG_TAG_RECT "<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" \
  fill=\"%s\" stroke=\"%s\" stroke-width=\"%d\"  />\n"

#define SUCCESS 0
#define ERROR_PARAMETER -1
#define OUT_OF_MEMORY -2
#define READ_ERROR_FILE -3
#define FILE_CORRUPT -4
#define QUIT -5
#define BLOCKSIZE 50
#define ERROR -6
#define EMPTY -9
#define NOT_A_NUMBER -10

typedef struct _Content_
{
  int id;
  int group_id;
  int coord_x;
  int coord_y;
  int radius;
  int height;
  int width;
  char object_type[2];
  char text_color[25];
  char line_color[25];
  int stroke_width;
} Content;

typedef struct _List_
{
  Content content;
  struct _List_ *next;
  struct _List_ *prev;
  struct _List_ *group_ptr;
} List;

// forward declarations
int isNumeric(char* input, int lenght);
int readString(char **command);
int readInteger(int *number);
int checkIDExists(List *list_root, int id);
int checkGroupExists(List *list_root, int group_id);
int searchAndInsert(List *object, List *list_root, int id, int group_id);
int createRect(List **list_root);
int createCircle(List **list_root);
int viewList(List *list_root);
int moveObject(List *list_root, int id);
int moveGroup(List *list_root, int id);
int move(List *list_root);
int checkParameter(int argc, char *argv);
int getFilename(char *argv, char *filename);
int commandPrompt(char *prompt, List **list_root);
int readConfig(char *filename, char *magic_number, char *prompt,
    int *size_x, int *size_y);
int writeSvg(List *list_root, int size_x, int size_y,
    char *filename, char *prompt);

//------------------------------------------------------------------------------
///
/// Main programm
///
/// @param argc number of arguments
/// @param argv arguments
///
/// @return 0  on success
///        -1  wrong parameter
///        -2  when out of memory
///        -3  couldn't read database
///        -4  file corrupt
///        -5  quit program
///        -6  error
///        -9  empty file
//
int main(int argc, char *argv[])
{
  int check_errors = 0;
  char magic_number[6];
  char prompt[10];
  char *filename = malloc(sizeof(char) * BLOCKSIZE);
  int size_x;
  int size_y;
  free(NULL);


  List *list_root;
  List* temp_list;


  if ((list_root = malloc(sizeof(List))) == NULL)
  {
    printf("error: out of memory\n");
    free(filename);
    filename = NULL;
  }
  else
  {
    list_root->next = NULL;
    list_root->prev = NULL;
    list_root->group_ptr = NULL;
    list_root->content.id = -1;
    list_root->content.group_id = -1;
    list_root->content.coord_x = 0;
    list_root->content.coord_y = 0;
    list_root->content.radius = 0;
    list_root->content.stroke_width = 0;

    if (checkParameter(argc, argv[1]) == 0)
    {
      if (strlen(argv[1]) > 3)
      {
        getFilename(argv[1], filename);
        check_errors = readConfig(filename, magic_number, prompt, &size_x,
            &size_y);
        if (check_errors != FILE_CORRUPT)
        {
          while (commandPrompt(prompt, &list_root) == QUIT)
          {
            if ((check_errors = writeSvg(list_root, size_x, size_y, filename,
                prompt) != SUCCESS))
            {
              continue;
            }
            else
              break;
          }
        }
      }
      else
      {
        printf("error: cannot read configfile %s\n", filename);
        free(filename);
        filename = NULL;
        return FILE_CORRUPT;
      }
    }
  }

  //Freigabe einzelner Objekte aus Liste
  List* buffer = list_root->next;
  while(buffer != NULL)
  {
   temp_list = buffer;
   buffer = buffer->next;
   free(temp_list);
  }

  free(filename);
  free(list_root);
  return SUCCESS;
}

//------------------------------------------------------------------------------
///
/// checks if parameter is an integer number
///
/// @param argc number of arguments
/// @param argv arguments
///
/// @return 0  on success
///        -10  not a number
//
int isNumeric(char* input, int lenght)
{
  int counter;
  for (counter = 0; counter < lenght; counter++)
  {
    if ((input[counter] < 48 || input[counter] > 57) && input[counter] != 45)
    {
      printf("error: invalid parameter - please enter an integer number\n");
      return NOT_A_NUMBER;
    }
  }
  return SUCCESS;
}

//------------------------------------------------------------------------------
/// reads and saves string of function
///
/// @param
/// @param
///
/// @return 0  on success
///        -2  when out of memory
//
int readString(char **command)
{
  int block_counter, index, str_length = 0;
  char* buffer;

  *command = malloc(sizeof(char) * BLOCKSIZE);
  block_counter = 1;

  for (index = 0;; index++)
  {
    if ((index + 2) % 50 == 0)
    {
      block_counter++;
      buffer = realloc(*command, sizeof(char) * sizeof(BLOCKSIZE)
          * block_counter);
      if (!buffer)
      {
        free(*command);
        return OUT_OF_MEMORY;
      }
      else
        *command = buffer;
    }
    (*command)[index] = fgetc(stdin);
    if ((*command)[index] == '\n')
      break;
  }
  (*command)[index] = '\0';
  str_length = strlen(*command);
  buffer = realloc(*command, sizeof(char) * (str_length + 1));
  if (!buffer)
  {
    free(*command);
    return OUT_OF_MEMORY;
  }
  else
    *command = buffer;
  return SUCCESS;
}

//------------------------------------------------------------------------------
/// reads and saves integer of function
///
/// @param is_numeric isnumeric checks parameter inavlid
/// @param
///
/// @return 0  on success
///        -2  when out of memory
///       -10  not a number
//
int readInteger(int *number)
{
  int str_length = 0, counter = 0, is_numeric = 0, num_of_blocks = 1;
  *number = 0;
  char *buffer = 0;
  char *input = malloc(BLOCKSIZE * sizeof(char));
  while (1)
  {
    if ((counter + 2) % 50 == 0)
    {
      num_of_blocks++;
      buffer = realloc(input, num_of_blocks * BLOCKSIZE * sizeof(char));
      if (buffer == 0)
      {
        free(input);
        return OUT_OF_MEMORY;
      }
      else
      {
        input = buffer;
      }
    }
    input[counter] = fgetc(stdin);
    if (strncmp(&input[counter], "\n", 1) == 0)
    {
      break;
    }
    counter++;
  }
  input[counter] = '\0';
  if (counter == 0)
  {
    *number = 0;
    free(input);
    input = NULL;
    return EMPTY;
  }
  is_numeric = isNumeric(input, counter);

  str_length = strlen(input);
  input = realloc(input, sizeof(str_length));

  if (is_numeric == NOT_A_NUMBER)
  {
    return NOT_A_NUMBER;
  }
  else
  {
    *number = atoi(input);
  }
  return SUCCESS;
}

//------------------------------------------------------------------------------
//
/// Checks if id exist
///
/// @param
/// @param
///
//
int checkIDExists(List *list_root, int id)
{
  List *temp_list;
  temp_list = list_root;
  while (temp_list->next != NULL)
  {
    temp_list = temp_list->next;
    if (temp_list->content.id == id)
      return 1;
  }
  return 0;
}

//------------------------------------------------------------------------------
//
/// checks if group exist
///
/// @param
/// @param
//
int checkGroupExists(List *list_root, int group_id)
{
  List *temp_list;
  temp_list = list_root;
  while (temp_list->next != NULL)
  {
    temp_list = temp_list->next;
    if (temp_list->content.group_id == group_id)
      return 1;
  }
  return 0;
}

//------------------------------------------------------------------------------
//
/// search and finds right grouo and id
///
/// @param
/// @param
///
/// @return 0  on success
///        -6  error
//
int searchAndInsert(List *object, List *list_root, int id, int group_id)
{
  List *temp_list;
  List *prev_temp_list;
  List *last_list;
  temp_list = list_root;

  if (temp_list == 0)
  {
    return ERROR;
  }

  if (temp_list->next == 0)
  {
    temp_list->next = object;
    temp_list->prev = NULL;
    temp_list->group_ptr = object;
    object->next = NULL;
    object->prev = temp_list;
    object->group_ptr = NULL;
    return SUCCESS;
  }
  else // if there are other objects already in list
  {
    if (checkGroupExists(list_root, object->content.group_id)) //group exists
    {
      while (temp_list->content.group_id != object->content.group_id)
      {
        prev_temp_list = temp_list;
        temp_list = temp_list->group_ptr;
      }
      if (object->content.id < temp_list->content.id)
      { // insert as first element of a group
        temp_list->prev->next = object;
        object->prev = temp_list->prev;
        object->group_ptr = temp_list->group_ptr;
        object->next = temp_list;
        temp_list->group_ptr = NULL;
        temp_list->prev = object;
        prev_temp_list->group_ptr = object;
      }
      else
      { // insert not as first element of a group
        while (temp_list->next != NULL && object->content.id
            < temp_list->next->content.id && object->content.group_id
            == temp_list->next->content.group_id)
          temp_list = temp_list->next;
        if (temp_list->next != NULL)
        {
          temp_list->next->prev = object;
          object->next = temp_list->next;
          object->prev = temp_list;
          temp_list->next = object;
        }
        else
        {
          object->next = NULL;
          object->prev = temp_list;
          temp_list->next = object;
        }
      }
    }
    else
    {
      while ((temp_list->content.group_id < object->content.group_id)
          && temp_list->group_ptr != NULL)
      {
        prev_temp_list = temp_list;
        temp_list = temp_list->group_ptr;
      }
      if (temp_list->content.group_id > object->content.group_id)
      {
        temp_list->prev->next = object;
        object->prev = temp_list->prev;
        object->group_ptr = temp_list;
        object->next = temp_list;
        temp_list->prev = object;
        prev_temp_list->group_ptr = object;
      }
      else
      {
        last_list = list_root;
        while (last_list->next)
          last_list = last_list->next;

        last_list->next = object;
        object->prev = last_list;
        object->group_ptr = NULL;
        object->next = NULL;
        prev_temp_list->group_ptr = object;

      }
    }

  }

  return SUCCESS;
}

//------------------------------------------------------------------------------
//
/// creates rect
///
/// @param
/// @param
///
/// @return 0  on success
///        -2  when out of memory
///        -6  error
//
int createRect(List **list_root)
{
  int id, coord_x, coord_y, width, stroke_width, height, number;
  int group_id;
  char *text_color = malloc(sizeof(BLOCKSIZE));
  char *line_color = malloc(sizeof(BLOCKSIZE));

  List *new_rect = malloc(sizeof(List));

  while (1)
  {
    number = 0;
    printf("  id? ");
    id = readInteger(&number);
    if (id == NOT_A_NUMBER || id == EMPTY)
    {
      continue;
    }
    else
      id = number;
    if (checkIDExists(*list_root, number))
    {
      printf("error: id does already exist\n");
      continue;
    }
    break;
  }

  while (1)
  {
    number = 0;
    printf("  x? ");
    coord_x = readInteger(&number);
    if (coord_x == NOT_A_NUMBER || coord_x == EMPTY)
    {
      continue;
    }
    else
      coord_x = number;
    break;
  }

  while (1)
  {
    printf("  y? ");
    coord_y = readInteger(&number);
    if (coord_y == NOT_A_NUMBER || coord_y == EMPTY)
    {
      continue;
    }
    else
      coord_y = number;
    break;
  }

  while (1)
  {
    printf("  width? ");
    width = readInteger(&number);
    if (width == NOT_A_NUMBER || width == EMPTY)
    {
      continue;
    }
    else
      width = number;
    break;
  }

  while (1)
  {
    printf("  height? ");
    height = readInteger(&number);
    if (height == NOT_A_NUMBER || height == EMPTY)
    {
      continue;
    }
    else
      height = number;
    break;
  }

  while (1)
  {
    printf("  fill? ");
    readString(&text_color);
    if (!(strcmp(text_color, "")))
    {
      continue;
    }
    break;
  }

  while (1)
  {
    printf("  stroke? ");
    readString(&line_color);
    if (!(strcmp(line_color, "")))
    {
      continue;
    }
    break;
  }

  while (1)
  {
    printf("  stroke-width? ");
    stroke_width = readInteger(&number);
    if (stroke_width == NOT_A_NUMBER || stroke_width == EMPTY)
    {
      continue;
    }
    else
      stroke_width = number;
    break;
  }

  while (1)
  {
    printf("  group? ");
    group_id = readInteger(&number);
    if (group_id == NOT_A_NUMBER || group_id == EMPTY)
    {
      continue;
    }
    else
      group_id = number;
    break;
  }

  if ((new_rect = malloc(sizeof(List))) == NULL)
  {
    printf("error: out of memory\n");
    return OUT_OF_MEMORY;
  }

  new_rect->content.id = id;
  new_rect->content.group_id = group_id;
  new_rect->content.coord_x = coord_x;
  new_rect->content.coord_y = coord_y;
  new_rect->content.width = width;
  new_rect->content.height = height;
  strcpy(new_rect->content.object_type, "r");
  strcpy(new_rect->content.text_color, text_color);
  strcpy(new_rect->content.line_color, line_color);
  new_rect->content.stroke_width = stroke_width;
  new_rect->group_ptr = NULL;
  new_rect->next = NULL;
  new_rect->prev = NULL;

  if (searchAndInsert(new_rect, *list_root, new_rect->content.id,
      new_rect->content.group_id) != SUCCESS)
  {
    return ERROR;
  }

  free(text_color);
  free(line_color);

  return SUCCESS;
}

//------------------------------------------------------------------------------
//
/// creates circle
///
/// @param
/// @param
///
/// @return 0  on success
///        -2  when out of memory
///        -6  error
//
int createCircle(List **list_root)
{
  int id;
  int coord_x;
  int coord_y;
  int radius;
  int stroke_width;
  int group_id;
  int number;
  char *text_color = malloc(sizeof(BLOCKSIZE));
  char *line_color = malloc(sizeof(BLOCKSIZE));
  List *new_circle = malloc(sizeof(List));

  while (1)
  {
    printf("  id? ");
    id = readInteger(&number);
    if (id == NOT_A_NUMBER || id == EMPTY)
    {
      continue;
    }
    else
      id = number;
    if (checkIDExists(*list_root, id))
    {
      printf("error: id does already exist\n");
      continue;
    }
    break;
  }

  while (1)
  {
    printf("  x? ");
    coord_x = readInteger(&number);
    if (coord_x == NOT_A_NUMBER || coord_x == EMPTY)
    {
      continue;
    }
    else
      coord_x = number;
    break;
  }

  while (1)
  {
    printf("  y? ");
    coord_y = readInteger(&number);
    if (coord_y == NOT_A_NUMBER || coord_y == EMPTY)
    {
      continue;
    }
    else
      coord_y = number;
    break;
  }

  while (1)
  {
    printf("  r? ");
    radius = readInteger(&number);
    if (radius == NOT_A_NUMBER || radius == EMPTY)
    {
      continue;
    }
    else
      radius = number;
    break;
  }

  while (1)
  {
    printf("  fill? ");
    readString(&text_color);
    if (!(strcmp(text_color, "")))
    {
      continue;
    }
    break;
  }

  while (1)
  {
    printf("  stroke? ");
    readString(&line_color);
    if (!(strcmp(line_color, "")))
    {
      continue;
    }
    break;
  }

  while (1)
  {
    printf("  stroke-width? ");
    stroke_width = readInteger(&number);
    if (stroke_width == NOT_A_NUMBER || stroke_width == EMPTY)
    {
      continue;
    }
    else
      stroke_width = number;
    break;
  }

  while (1)
  {
    printf("  group? ");
    group_id = readInteger(&number);
    if (group_id == NOT_A_NUMBER || group_id == EMPTY)
    {
      continue;
    }
    else
      group_id = number;
    break;
  }

  if ((new_circle = malloc(sizeof(List))) == NULL)
  {
    printf("error: out of memory\n");
    return OUT_OF_MEMORY;
  }

  new_circle->content.id = id;
  new_circle->content.group_id = group_id;
  new_circle->content.coord_x = coord_x;
  new_circle->content.coord_y = coord_y;
  new_circle->content.radius = radius;
  strcpy(new_circle->content.object_type, "c");
  strcpy(new_circle->content.text_color, text_color);
  strcpy(new_circle->content.line_color, line_color);
  new_circle->content.stroke_width = stroke_width;
  new_circle->group_ptr = NULL;
  new_circle->next = NULL;
  new_circle->prev = NULL;

  if (searchAndInsert(new_circle, *list_root, new_circle->content.id,
      new_circle->content.group_id) != SUCCESS)
    return ERROR;

  free(text_color);
  free(line_color);

  return SUCCESS;
}

//------------------------------------------------------------------------------
//
/// View list
///
/// @param
/// @param
///
/// @return 0  on success
///        -6  error
//
int viewList(List *list_root)
{
  List *counter_list;

  if (list_root->next == NULL)
  {
    return ERROR;
  }

  counter_list = list_root->next;

  while (counter_list != NULL)
  {
    printf("[gr-%d][%d] %d %d\n", counter_list->content.group_id,
        counter_list->content.id, counter_list->content.coord_x,
        counter_list->content.coord_y);
    if (counter_list->next == NULL)
      break;

    counter_list = counter_list->next;
  }
  return SUCCESS;
}

//------------------------------------------------------------------------------
//
/// moves an object with values
///
/// @param
/// @param
///
/// @return 0  on success
///        -2  when out of memory
//
int moveObject(List *list_root, int id)
{
  int add_to_x;
  int x_is_ok;
  int add_to_y;
  int y_is_ok;
  List *temp_list;
  temp_list = list_root;
  while (temp_list->content.id != id)
  {
    temp_list = temp_list->next;
  }
  do
  {
    printf("  x? ");
    x_is_ok = readInteger(&add_to_x);
    if (x_is_ok == SUCCESS)
    {
      temp_list->content.coord_x += add_to_x;

      do
      {
        printf("  y? ");
        y_is_ok = readInteger(&add_to_y);
        if (y_is_ok == SUCCESS)
        {
          temp_list->content.coord_y += add_to_y;
        }
        if (y_is_ok == OUT_OF_MEMORY)
        {
          return y_is_ok;
        }
      }
      while (y_is_ok != SUCCESS);
    }
    if (x_is_ok == OUT_OF_MEMORY)
    {
      return x_is_ok;
    }
  }
  while (x_is_ok != SUCCESS);
  return SUCCESS;
}

//------------------------------------------------------------------------------
//
/// Moves group with values
///
/// @param
/// @param
///
/// @return 0  on success
///        -2  when out of memory
//
int moveGroup(List *list_root, int id)
{
  int add_to_x;
  int x_is_ok;
  int add_to_y;
  int y_is_ok;
  List *temp_list;
  temp_list = list_root;

  do
  {
    printf("  x?");
    x_is_ok = readInteger(&add_to_x);
    if (x_is_ok == SUCCESS)
    {
      do
      {
        printf("  y?");
        y_is_ok = readInteger(&add_to_y);

        if (y_is_ok == OUT_OF_MEMORY)
        {
          return y_is_ok;
        }
      }
      while (y_is_ok != SUCCESS);
    }
    if (x_is_ok == OUT_OF_MEMORY)
    {
      return x_is_ok;
    }
  }
  while (x_is_ok != SUCCESS);

  while (temp_list)
  {
    if (temp_list->content.group_id == id)
    {
      temp_list->content.coord_x += add_to_x;
      temp_list->content.coord_y += add_to_y;
    }
    temp_list = temp_list->next;
  }

  return SUCCESS;
}

//------------------------------------------------------------------------------
//
/// moves group or id
///
/// @param
/// @param
///
/// @return 0  on success
///       -10  not a number
//
int move(List *list_root)
{
  int id;
  int is_numeric;
  int move_group = 0;
  char *id_temp = malloc(sizeof(BLOCKSIZE));


  while (1)
  {
    do
    {
      printf("  id? ");
      readString(&id_temp);
      if (!(strcmp(id_temp, "")))
      {
        return ERROR;
      }

      if (strncmp(id_temp, "gr-", 3) == 0)
      {
        id_temp = id_temp + 3;
        move_group = 1;
      }

      is_numeric = isNumeric(id_temp, strlen(id_temp));

    }
    while (is_numeric == NOT_A_NUMBER);

    id = atoi(id_temp);

    if (checkIDExists(list_root, id) || checkGroupExists(list_root, id))
    {
      if (move_group)
      {
        moveGroup(list_root, id);
      }
      else
      {
        moveObject(list_root, id);
      }
      return SUCCESS;
    }
    else
    {
      printf("error: id does not exist\n");
    }
  }
}

//------------------------------------------------------------------------------
//
/// checks is function is a parameter
///
/// @param
/// @param
///
/// @return 0  on success
///        -1  wrong parameter
//
int checkParameter(int argc, char *argv)
{
  char parameter[] = PARAMETER;

  if (argc != 2 || (strncmp(parameter, argv, 3) != 0))
  {
    printf("usage: ex2 -c=configfile\n");
    return ERROR_PARAMETER;
  }
  return SUCCESS;
}

//------------------------------------------------------------------------------
//
/// creates name of file
///
/// @param
/// @param
///
/// @return 0  on success
///        -2  when out of memory
//
int getFilename(char *argv, char *filename)
{
  int index;
  int counter;
  int str_length = 0;
  char* buffer = NULL;

  counter = 1;
  for (index = 0; argv[index] != '\0'; index++)
  {
    if ((index + 2) % BLOCKSIZE == 0)
    {
      buffer = realloc(filename, sizeof(char) * sizeof(BLOCKSIZE) * counter);
      if (buffer == NULL)
      {
        free(filename);
        filename = NULL;
        return OUT_OF_MEMORY;
      }
      else
        filename = buffer;
    }
    filename[index] = argv[index + 3];
  }
  filename[index] = '\0';

  str_length = strlen(filename);
  buffer = realloc(filename, sizeof(char) * (str_length + 1));
  if (!buffer)
  {
    free(filename);
    filename = NULL;
    return OUT_OF_MEMORY;
  }
  else
    filename = buffer;
  return SUCCESS;
}

//------------------------------------------------------------------------------
//
/// reads in stdin,
///
/// @param
/// @param
///
/// @return 0  on success
///        -5  quit program
//
int commandPrompt(char *prompt, List **list_root)
{
  char *command = NULL;
  int error_code;

  while (1)
  {
    printf("%s> ", prompt);
    readString(&command);

    if (strcmp(command, "quit") == 0)
    {
      free(command);
      return QUIT;
    }
    else
      if (strcmp(command, "circle") == 0)
      {
        error_code = createCircle(list_root);
        if (error_code != SUCCESS)
        {
          continue;
        }
        continue;
      }
      else
        if (strcmp(command, "rect") == 0)
        {
          error_code = createRect(list_root);
          if (error_code != SUCCESS)
          {
            continue;
          }
          continue;
        }
        else
          if (strcmp(command, "list") == 0)
          {
            viewList(*list_root);
            continue;
          }

          else
            if (strcmp(command, "move") == 0)
            {
              move(*list_root);
              continue;
            }
            else
              if (strcmp(command, "\0") == 0)
              {
                continue;
              }
              else
              {
                printf("error: unknown command\n");
                continue;
              }
    free(command);
    command = NULL;
  }
  free(command);
  return SUCCESS;
}

//------------------------------------------------------------------------------
//
/// checks if the ConfigFile is correct
///
/// @param
/// @param
///
/// @return 0  on success
///        -4  file_corrupt
//
int readConfig(char *filename, char *magic_number, char *prompt,
    int *size_x, int *size_y)
{
  int counter = 0;
  FILE *config;
  if (!(config = fopen(filename, "r")))
  {
    printf("error: cannot read configfile %s\n", filename);
    return FILE_CORRUPT;
  }

  for (counter = 0; counter < 5; counter++)
    magic_number[counter] = fgetc(config);
  magic_number[counter] = '\0';
  if ((strcmp(MAGIC_NUMBER, magic_number)) != 0)
  {
    printf("error: configfile %s corrupt\n", filename);
    return FILE_CORRUPT;
  }

  for (counter = 0; counter < 4; counter++)
  {
    prompt[counter] = fgetc(config);
    if (counter == 4)
    {
      if (prompt[counter] != '\0')
      {
        printf("error: configfile %s corrupt\n", filename);
        return FILE_CORRUPT;
      }
    }
  }

  fread(size_x, sizeof(int), 1, config);
  fread(size_y, sizeof(int), 1, config);

  // check if size_x, size_y makes sense
  if (size_x <= 0 || size_y <= 0)
  {
    printf("error: configfile %s corrupt\n", filename);
    return FILE_CORRUPT;
  }
  fclose(config);
  return SUCCESS;
}

//------------------------------------------------------------------------------
//
/// saves created objects into data
///
/// @param
/// @param
///
/// @return 0  on success
///        -6  error
//
int writeSvg(List *list_root, int size_x, int size_y,
    char *filename, char *prompt)
{
  char *html;
  char *confirmation;
  FILE *svg;
  List *temp_list;
  temp_list = list_root;

  while(1)
  {
    printf("  file? ");
    readString(&html);
    if(!(strcmp(html, "")))
    {
      printf("error: cannot write to savefile %s. Quit anyway? (y/n)\n", html);
      readString(&confirmation);
      if(!(strcmp(confirmation, "y")))
      {
        free(html);
        free(confirmation);
        return QUIT;
      }
      if(!(strcmp(confirmation, "n")))
      {
        continue;
      }
      else
      {
        continue;
      }
    }
    break;
  }

  while (1)
  {
    if ((svg = fopen(html, "r")))
    {
      printf("warning: file %s exists and will be replaced. "
          "Do you want to proceed? (y/n)\n", html);
      readString(&confirmation);
      switch (*confirmation)
      {
        case 'y':
        {
          svg = fopen(html, "w");
          fprintf(svg, HEADER, size_x, size_y);
          while (1)
          {
            if (temp_list->next != NULL)
            {
              temp_list = temp_list->next;

              if (strcmp(temp_list->content.object_type, "c") == 0)
              {
                fprintf(svg, SVG_TAG_CIRCLE, temp_list->content.coord_x,
                    temp_list->content.coord_y, temp_list->content.radius,
                    temp_list->content.text_color,
                    temp_list->content.line_color,
                    temp_list->content.stroke_width);
              }

              if (strcmp(temp_list->content.object_type, "r") == 0)
              {
                fprintf(svg, SVG_TAG_RECT, temp_list->content.coord_x,
                    temp_list->content.coord_y, temp_list->content.width,
                    temp_list->content.height, temp_list->content.text_color,
                    temp_list->content.line_color,
                    temp_list->content.stroke_width);
              }
            }

            if (temp_list->next == NULL)
            {
              break;
            }
          }
          fprintf(svg, FOOTER);
          fclose(svg);
          free(html);
          html = NULL;
          free(confirmation);
          confirmation = NULL;
          return SUCCESS;
        }

        case 'n':
        {
          free(html);
          free(confirmation);
          return ERROR;
        }

      }
    }
    else
    {
      svg = fopen(html, "w");
      fprintf(svg, HEADER, size_x, size_y);
      while (1)
      {
        if (temp_list->next != NULL)
        {
          temp_list = temp_list->next;

          if (strcmp(temp_list->content.object_type, "c") == 0)
          {
            fprintf(svg, SVG_TAG_CIRCLE, temp_list->content.coord_x,
                temp_list->content.coord_y, temp_list->content.radius,
                temp_list->content.text_color, temp_list->content.line_color,
                temp_list->content.stroke_width);
          }
          if (strcmp(temp_list->content.object_type, "r") == 0)
          {
            fprintf(svg, SVG_TAG_RECT, temp_list->content.coord_x,
                temp_list->content.coord_y, temp_list->content.width,
                temp_list->content.height, temp_list->content.text_color,
                temp_list->content.line_color,
                temp_list->content.stroke_width);
          }
        }
        if (temp_list->next == NULL)
          break;
      }
      fprintf(svg, FOOTER);
      fclose(svg);
      free(html);
      html = NULL;

      return SUCCESS;
    }
  }
}
